home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Utilities Professional 1-1500
/
Utilities Professional 1-1500 (1994)(WPD)[!].iso
/
12511500
/
var1256.dms
/
var1256.adf
/
MyCLI
/
MyCLI.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-03-04
|
55KB
|
2,081 lines
/*
Original usenet posting header:
From: uwvax!3comvax!mykes (Mike Schwartz)
Newsgroups: net.micro.amiga
Subject: MyCLI - CLI/Terminal program
Date: 31 Dec 85 09:15:18 GMT
Organization: 3Com Corp; Mountain View, CA
* MyCLI - a replacement for the standard AmigaDos CLI
* Programmed by Mike Schwartz (C)1985 MS Software, All Rights Reserved!
* Feel free to give this software away, in any form, for no charge only.
*/
/*
the original version 1.0 was by Mike Schwartz
all of RTW (Rick Wirch's) revisions make up version 1.01
these include:
o all of command line editing capabilities [getcommand()]
o 'history' ability with up and down keys
o refinement and cleanup of window opening at startup
o corrections in executive() function
o limited redirection capabilities
o increase in capabilities of prompt printer
o copy's ability to understand directories and only one
parameter to copy into current directory
o copy's ability to understand '*' as console device
o recursive directory ability using "-r" or "opt a"
o addition of 'list' like command
o 'more' command to view a file a page at a time
o marked increase in the speed of 'type' by buffering
o multiple refinements in code.
3/28/86 Djj all of Djj revisions make up version 1.02
3/28/86 Djj Converted source to compile with Aztec C compiler.
Added array of pointers *args[] to simulate *argv[]
Manx doesn't allocate any more pointers than what are
on the command line. The scheme used here requires at
5 pointers be allocated on entry.
Added Directories count to list command. Also added
1 block, 512 bytes to totals for each directory.
MANX compiler objects to char pointers initialized with
a quoted string. It generates correct code (mostly) but
bores me with WARNING messages. To eliminate this problem:
compile with: cc -aso ram:mycli.asm
assemble with: as -s1900 -o mycli.o ram:mycli.asm
link with: ln -o mycli mycli.o -lc
3/31/86 Djj Fixed date problem.
4/01/86 Djj Added Phase of the Moon to date. Changed serial driver
to handle XON/XOFF.
4/02/86 Djj Fixed my date problem. date would crash when #of days was
negative (somewhere around the year 2045 )
4/21/86 RTW fixed two bugs in the 'cd' command
thru leading slashes now move up the tree one lvl per slash
5/07/86 using just slashes now removes trailing slash
fixed several bugs in the 'copy' command
copying '*' to a file now works correctly
copying to a directory works for ALL cases
having a complex path for the both files now works
better error checking all around
fixed bug in the 'define' command with FreeMem
fixed bug in 'type' with the last line typed
more command with redirection does not require input
redirection can now be anywhere in the command
added redirection capabilities to all commands
added command path search
added command chaining ability
added new command 'set'
added power up copying of 'run' to ram:
reformatted and generally made code more readable
put better error checking for weird cases in commands
added some comments and changed version number to 2.00
*/
/* Remove the next line if not using the Aztec C compiler */
#define AZTEC 1 /* defined if using Aztec C compiler */
/* #define MODEM */ /* to include simple terminal capabilities */
#define MOON /* output phase of moon with date */
#ifdef AZTEC
#define stpchr(s,c) index(s,c)
#define ABS(val) (((val) < 0) ? (-(val)) : (val))
#else
extern UBYTE *stpchr();
#endif
#include "exec/types.h"
#include "exec/exec.h"
#include "libraries/dos.h"
#include "libraries/dosextens.h"
#ifdef MODEM
#include "devices/serial.h"
#endif
#ifdef MOON
extern UBYTE *moon();
#endif
#define ESC 0x1b
#define BRK 0x3
#define WriteWork() Write(mycli_outfp, work, (long)strlen(work))
#ifdef TRUE
#undef TRUE /* MANX defines these in an unusual way */
#undef FALSE
#endif
#define TRUE 1
#define FALSE 0
/*
* External function references
*/
extern struct MsgPort *CreatePort();
extern struct FileLock *CreateDir();
extern struct FileLock *CurrentDir();
extern struct FileLock *Lock();
extern struct FileHandle *Open();
extern LONG Seek(), Read(), Write(), ExNext();
extern VOID Close(), FreeMem(), DateStamp(), UnLock();
extern UBYTE *stpblk(), *AllocMem();
/*
* Forward function references
*/
VOID capture(), cd(), copy(), date(), define_function_key(), delete(),
dir(), delete(), endcli(), help(), list(), ls(), md(), more(),
newcli(), offline(), rename(), set(), setcomment(),
TerminalMode(), time(), type(), whatis();
VOID batchfile(), CommandInterpreter(), doserr(), executive(),
getcommand(), makename(), showprompt();
/*
* Tables
*/
struct {
UBYTE *cmdname;
VOID (*cmdfunc)();
} command_table[] = {
#ifdef MODEM
(UBYTE *)"capture", &capture,
#endif
(UBYTE *)"cd", &cd,
(UBYTE *)"copy", ©,
(UBYTE *)"date", &date,
(UBYTE *)"define", &define_function_key,
(UBYTE *)"def", &define_function_key,
(UBYTE *)"delete", &delete,
(UBYTE *)"del", &delete,
(UBYTE *)"dir", &dir,
(UBYTE *)"endcli", &endcli,
(UBYTE *)"help", &help,
(UBYTE *)"ls", &dir,
(UBYTE *)"list", &list,
(UBYTE *)"makedir", &md,
(UBYTE *)"md", &md,
(UBYTE *)"more", &more,
(UBYTE *)"mv", &rename,
(UBYTE *)"newcli", &newcli,
#ifdef MODEM
(UBYTE *)"online", &TerminalMode,
(UBYTE *)"offline", &offline,
#endif
(UBYTE *)"rename", &rename,
(UBYTE *)"setcomment", &setcomment,
(UBYTE *)"set", &set,
#ifdef MODEM
(UBYTE *)"terminal", &TerminalMode,
#endif
(UBYTE *)"time", &time,
(UBYTE *)"type", &type,
(UBYTE *)"whatis", &whatis,
NULL, NULL
};
UBYTE *help_messages[] = {
#ifdef MODEM
"capture = capture file from modem",
#endif
"cd = change directory",
"copy = copy from one file to another",
"date = show current date",
"def = define a function key (def f1 dir)",
"define = \" \" (define f1 dir)",
"del = delete file or subdirectory",
"delete = \" \"",
"dir = like AmigaDOS 'dir'",
"endcli = exit to previous cli",
"help = print this list",
"list = like AmigaDOS 'list'",
"ls = like AmigaDOS 'dir'",
"makedir = make a new subdirectory",
"md = \" \"",
"more = view a file a page at a time",
"mv = rename a file or directory",
"newcli = birth another mycli task",
#ifdef MODEM
"online = enter or re-enter dumb terminal mode",
"offline = terminate communication",
#endif
"set = set system variables like 'path', 'prompt', or 'chain'",
"rename = rename a file or directory",
"setcomment = tag a file with a comment string",
#ifdef MODEM
"terminal = enter or re-enter dumb terminal mode",
#endif
"time = show current time",
"type = view a file",
"whatis = converts AmigaDos error codes to text",
0
};
UBYTE *function_key_definitions[20] = {
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0
};
struct {
WORD code;
UBYTE *message;
} errorcodes[] = {
103, "insufficient free store",
104, "task table full",
120, "argument line invalid or too long",
121, "file is not an object module",
122, "invalid resident library during load",
203, "object already exists",
204, "directory not found",
205, "object not found",
206, "invalid window",
210, "invalid stream component name",
212, "object not of required type",
213, "disk not validated",
214, "disk write-protected",
215, "rename across devices attempted",
216, "directory not empty",
218, "device not mounted",
220, "comment too big",
221, "disk full",
222, "file is protected from deletion",
223, "file is protected from writing",
224, "file is protected from reading",
225, "not a DOS disk",
226, "no disk in drive",
209, "packet request type unknown",
211, "invalid object lock",
219, "seek error",
232, "no more entries in directory",
0, 0 };
/*
* Globals
*/
UBYTE work[514];
UBYTE work2[514];
UBYTE *args[ 5 ]; /* AZTEC doesn't allocate any more argv's than
appear on command line, so we use our own array */
/*
* MyCli globals
*/
struct FileHandle *mycli_infp; /* all i/o goes thru these two */
struct FileHandle *mycli_outfp;
UBYTE prompt_string[74]; /* holds string to display prompt */
UBYTE chain_string[74]; /* holds character to chain commands */
UBYTE path_string[74]; /* holds string for search path */
UBYTE current_directory[74]; /* holds current directory string */
UBYTE cmdbuf[15][74]; /* queue of last 16 commands */
WORD mycli_id; /* process id of mycli */
WORD lsmode = 0; /* boolean 1=ls() 0=dir() */
WORD moremode = 0; /* boolean 1=more() 0=type() */
WORD quit = 0; /* boolean 1=quit recursion 0=no */
WORD indent = 0; /* indentation for ls command */
WORD currcmd = 0; /* current command for queue */
#ifdef MODEM
/*
* Terminal emulator stuff
*/
struct Message *mymessage;
struct IOExtSer *ModemReadRequest;
struct IOExtSer *ModemWriteRequest;
UBYTE *WelcomeMessage = "Entering Terminal Mode\nUse ^C for command mode\n";
UBYTE *GoodbyeMessage = "Disconnected\n";
UBYTE *OfflineMessage = "--- Offline ---\n";
UBYTE *OnlineMessage = "--- Online ---\n";
UBYTE rs_in[2], rs_out[2];
WORD bdoneflag = 0;
WORD TermEcho = 0;
WORD modem_online = 0;
WORD capturing_file = 0;
struct FileHandle *capture_fp;
#endif
/* -------------------------------------
* Start of function Main()
* -------------------------------------
*/
main(argc, argv)
int argc;
UBYTE *argv[];
{
UBYTE *nextptr;
UBYTE *ptr;
WORD i;
UBYTE cmd_string[74];
if ( argc != 6 )
{
args[1] = "505"; args[2] = "136";
args[3] = "134"; args[4] = "64";
args[5] = "1";
argc = 6;
}
else
for( i = 1; i < argc; i++)
args[ i ] = argv[ i ];
sprintf(work, "Raw:%s/%s/%s/%s/MyCli[%s]",
args[argc-5], args[argc-4], args[argc-3], args[argc-2], args[argc-1]);
mycli_id = atoi(args[ argc-1 ]);
mycli_infp = Open(work, MODE_NEWFILE);
if (mycli_infp == 0)
exit(1L);
mycli_outfp = mycli_infp;
strcpy( work, "V1.0 By\nMike Schwartz\nV2.0 by\nRick Wirch\n\xa91986\n");
WriteWork();
for ( i = 0; i < 16; i++)
cmdbuf[ i ][ 0 ] = '\0';
/* This is the default character for chaining commands */
set( "chain ,");
/* This is the default MyCLI prompt */
set( "prompt $e[1;32m$p>$n ");
/* This is the default search path for the AUTOEXEC.BAT file */
batchfile( "autoexec.bat" );
/* This is the default startup directory for MyCli */
cd( "df0:" );
/* This is the default search path for commands */
set( "path RAM:;.;SYS:C/;" );
if ( mycli_id == 1 ) /* first time MyCli is executed */
{
md( "RAM:C" ); /* put run command in ramdisk */
copy( "SYS:c/run RAM:C/run" ); /* and make system use it for Execute */
executive( "ASSIGN C: RAM:C" ); /* force Execute to look in RAM: */
}
/* Main program loop */
while (TRUE)
{
showprompt(); /* show the custom prompt */
getcommand( cmd_string ); /* get a command from the user */
nextptr = cmd_string; /* execute chained commands */
while ( *nextptr )
{
for ( ptr = nextptr; *ptr && *ptr != chain_string[ 0 ]; ptr++ )
;
if ( *ptr )
*ptr++ = '\0';
CommandInterpreter( nextptr ); /* shuck off command to execute */
nextptr = ptr;
} /* end of while their is a string */
}
} /* end of function main() */
/* -------------------------------------------------------
* Miscellaneous functions for internal commands or Main()
* -------------------------------------------------------
*/
/*
* Declaring fh as a local in this routine, batch files may be nested
* as deep as the stack and memory will allow. This is a simple batchfile
* executer ( that is it does not understand IF, SKIP, .KEY, etc. )
* but it does understand MyCLI internal commands, which Execute does not.
*/
VOID batchfile(batchname)
UBYTE *batchname;
{
struct FileHandle *fh;
register WORD i;
WORD done;
UBYTE buf[74];
fh = Open(batchname, MODE_OLDFILE);
if ( fh == NULL )
return;
done = FALSE;
while ( !done )
{
for (i = 0; i < 70; i++)
{
if (Read(fh, &buf[i], 1L) == 0)
{
Close( fh );
done = TRUE;
break;
}
if (buf[ i ] == 0x0a)
break;
}
buf[ i ] = '\0';
showprompt();
sprintf(work, "%s\n", buf);
WriteWork();
CommandInterpreter( buf );
}
}
/*
* Scan through the command table for the string and invoke the function
* to do the actual work of the command. Each of these commands is
* defined below, and the functions each take a pointer to the
* string containing the arguments passed the command line.
*/
VOID CommandInterpreter( command )
UBYTE *command;
{
struct FileHandle *oldfile;
struct FileHandle *tempfh;
WORD i;
WORD found;
UBYTE *ptr;
UBYTE *pc;
UBYTE *name;
UBYTE trashbuf[74];
strcpy( trashbuf, command);
command = stpblk( trashbuf );
found = FALSE;
oldfile = NULL;
for ( ptr = command; *ptr && *ptr != '>' && *ptr != '<'; ptr++ )
;
if ( (*ptr == '>' || *ptr == '<') && *(ptr-1) == ' ' )
{ /* do file redirection */
oldfile = mycli_outfp; /* save old i/o handle */
name = stpblk( ptr + 1); /* skip any leading blanks */
for ( pc = name; *pc && *pc != ' '; pc++ )
; /* find end of redirection name */
if ( *pc )
*pc++ = '\0';
tempfh = Open( name, MODE_NEWFILE); /* open redirection */
if ( tempfh == NULL)
{
strcpy( work, "Can't open redirection file!\n");
WriteWork();
return;
}
if ( *ptr == '>' )
mycli_outfp= tempfh; /* redirect */
else
mycli_infp = tempfh;
strcpy( ptr-1, pc ); /* delete out the redir. stuff */
} /* end of redirection open */
ptr = command; /* point to beginning of cmd string */
/* Look for the command in the command table built into MyCLI */
for (i=0; command_table[ i ].cmdname[ 0 ] != '\0'; i++)
if (strncmp( ptr, &command_table[ i ].cmdname[ 0 ],
strlen(&command_table[ i ].cmdname[ 0 ]) ) == 0)
{
found = TRUE;
ptr = stpblk( &command[ strlen(command_table[i].cmdname) ] );
(*command_table[ i ].cmdfunc)( ptr ); /* call the command */
}
if ( !found) /* Not found, look for it on disk */
executive( command );
if ( oldfile ) /* close the redirection file(s) */
{
if ( mycli_outfp != oldfile )
Close( mycli_outfp );
if ( mycli_infp != oldfile )
Close( mycli_infp ); /* close up any redirection */
mycli_outfp = mycli_infp = oldfile; /* restore the defaults */
}
}
/*
* This function displays a description of the DOS error when it happens
*/
VOID doserr()
{
sprintf( work2, "%d", IoErr());
whatis( work2 );
}
/* This function is responsible for executing commands that are not
* internal to MyCLI. It performs the path expansion and understands
* .BAT or .CLI extensions.
*/
VOID executive(s)
UBYTE *s;
{
register UBYTE *pc;
register UBYTE *wptr;
register WORD found;
register WORD batchON;
struct FileLock *fl;
struct FileLock *ramlock;
if ( *s == '\0' )
return; /* no command so just return */
/* get the first token off of the command line into work. */
pc = &work[ 0 ];
while ( *s && (*pc = *s++) != ' ' )
pc++;
*pc = '\0'; /* null terminate work[] */
s = stpblk( s ); /* skip spaces , s points at arguments */
strcpy( work2, work ); /* save first token in work2 */
/* check for MyCLI batch file invocation. */
strcpy( work, work2 );
strcat( work, ".bat" );
fl = Lock(work, ACCESS_READ);
if (fl != NULL ) /* MyCLI batch file exists */
{
UnLock(fl); /* free the lock obtained */
batchfile(work); /* execute the batch file */
return; /* done our work */
}
/* .cli files are batch files to be run by the */
/* standard cli, using the execute command. */
strcpy(work, work2); /* preserve the first token again */
strcat(work, ".cli");
fl = Lock(work, ACCESS_READ);
if (fl != NULL) /* cli batch file exists */
{
batchON = TRUE;
strcpy( work2, work ); /* put batch name first */
strcat( work2, " "); /* add a space before the params */
strcat( work2, s); /* add the params */
strcpy( work , "execute");
UnLock( fl ); /* free the lock obtained */
}
else
{
batchON = FALSE;
found = FALSE;
/* do the path search */
pc = &path_string[ 0 ];
while ( *pc )
{
wptr = &work[ 0 ]; /* set wptr to start of work[] */
while ( *pc && (*wptr = *pc) != ';' )
pc++, wptr++; /* copy path prefix into work array */
*wptr = '\0'; /* null terminate work[] */
pc++; /* advance over the semi-colon */
if ( work[ 0 ] == '.' ) /* dot means current dir */
work[ 0 ] = '\0';
strcat( work, work2 ); /* add the command */
fl = Lock( work, ACCESS_READ);
if ( fl != NULL)
{
UnLock( fl);
found = TRUE;
break;
}
} /* end of while */
if ( !found )
strcpy( work, work2); /* restore the command in work[] */
strcpy( work2, s); /* put the params in work2[] */
} /* end of else clause */
strcat( work, " < * "); /* redirect input */
if ( *work2 )
strcat( work, work2 ); /* add the parameters */
ramlock = Lock( "RAM:C", ACCESS_READ );
if ( ramlock )
UnLock( ramlock );
else
batchON = FALSE;
if ( batchON )
Execute( "SYS:C/assign C: SYS:C", 0L, mycli_outfp );
if ( !Execute( work, 0L, mycli_outfp) )
doserr();
if ( batchON )
Execute( "SYS:C/assign C: RAM:C", 0L, mycli_outfp );
}
/*
* If a definition for the function key fkey exists ( 0-19), then
* the translation for the function key is copied to the string
* s, and this function returns 1. Otherwise, no translation
* exists, and this function returns 0;
*/
WORD function_key( fkey, s )
WORD fkey;
UBYTE *s;
{
register WORD i;
if ( function_key_definitions[ fkey ] != 0)
{
for( i = 0; function_key_definitions[ fkey ][ i ] != 0; i++)
s[ i ] = function_key_definitions[ fkey ][ i ];
s[ i ] = '\0';
return( TRUE );
}
return( FALSE );
}
/* This function is like a read of the keyboard except
* that if no key is pressed it immediately returns a zero
*/
UBYTE scr_csts()
{
UBYTE inbuf;
if (WaitForChar(mycli_infp, 1L) == 0)
return( 0 );
Read(mycli_infp, &inbuf, 1L);
return( inbuf );
}
/* This function uses the string 'prompt_string' and its embedded meaning
* to display a user defined prompt
*/
VOID showprompt()
{
register UBYTE *pc;
struct DateStamp dss;
pc = prompt_string;
while ( TRUE )
{
switch(*pc)
{
case '\0':
return;
case '$':
pc++;
switch( *pc )
{
case '\0':
return;
case 'b': case 'B': /* backspace */
strcpy( work, "\x08" );
break;
case 'd': case 'D': /* current date */
DateStamp(&dss);
dates(work, &dss);
break;
case 'e': case 'E': /* escape character */
strcpy( work, "\x1b");
break;
case 'n': case 'N': /* normal video */
strcpy( work, "\x1b[0m");
break;
case 'p': case 'P': /* current path */
sprintf(work, "%s", current_directory);
break;
case 'r': case 'R': /* reverse video */
strcpy( work, "\x1b[7m");
break;
case 't': case 'T': /* current time */
DateStamp(&dss);
times(work, &dss);
break;
case 'v': case 'V':
strcpy( work, "MyCli rev. 2.0");
break;
case '_':
strcpy(work, "\n");
break;
}
pc++;
WriteWork();
continue;
default:
sprintf(work, "%c", *pc++);
WriteWork();
continue;
}
} /* end of while( TRUE ) loop */
}
/* This function is called at the end of every line displayed to the
* window, it allows the user to pause that output or abort it.
*/
WORD pause()
{
UBYTE inbuf;
switch( scr_csts() )
{
case ' ':
while ( (inbuf = scr_csts()) != ' ' )
if (inbuf == ESC || inbuf == BRK)
return( FALSE );
return( TRUE );
case ESC: case BRK:
return( FALSE );
default:
return( TRUE );
}
}
/*
* build an appropriate file specification for output file
*/
VOID makename( dirstr, filestr)
UBYTE *dirstr;
UBYTE *filestr;
{
register UBYTE *pc;
pc = &dirstr[ strlen(dirstr)-1 ];
if (*pc == ':') /* from device:filespec? */
strcat( dirstr, filestr);
else /* append a slash, but don't want '//' */
{
if (*pc != '/')
strcat(dirstr, "/");
strcat(dirstr, filestr);
}
}
/* This function gets a command line from the user. It performs the
* command line editing, simple history ability, function key expansion,
* and other assorted fun things.
*/
VOID getcommand(s)
UBYTE *s;
{
register WORD col;
register WORD i;
register WORD insert;
UBYTE event_buffer[ 32 ];
UBYTE c;
insert = FALSE;
for ( col = 0; col < 72; col++)
s[ col ] = '\0'; /* initialize string to NULLs */
col = 0;
while ( TRUE )
{
Read(mycli_infp, &c, 1L);
switch( c )
{
case 8: /* Backspace key */
if (col)
{
Write(mycli_outfp, "\x08\x9bP", 3L);
col--;
s[ col ] = '\0';
strcat( s, &s[ col+1 ]);
}
continue;
case 0x01: case 0x09: /* CTRL-A, CTRL-I or TAB key */
insert = !insert;
continue;
case 0x7f: /* DEL key */
Write(mycli_outfp, "\x9bP", 2L);
s[ col ] = '\0';
strcat( s, &s[ col+1 ]);
continue;
case 10: case 13: /* CR or LF are end line chars */
Write(mycli_outfp, "\n", 1L);
if ( *s )
{
strcpy( &cmdbuf[ currcmd ][ 0 ], s );
currcmd = ++currcmd & 15; /* make counter wrap */
}
break;
case ESC: case 24: /* ESC or ^X are kill line chars */
while( col )
{
Write( mycli_outfp, "\x08 \x08", 3L);
col--;
s[ col ] = '\0';
}
continue;
case 0x9b:
Read( mycli_infp, &c, 1L);
if ( isdigit(c) )
{
i = 0;
while ( isdigit(c) )
{
event_buffer[ i++ ] = c;
Read( mycli_infp, &c, 1L);
}
event_buffer[ i ] = '\0';
if ( function_key( atoi(event_buffer), s) )
{
sprintf( work, "%s\n", s);
WriteWork();
return;
}
}
else
switch( c)
{
case ' ': /* shifted cursor left and right */
Read( mycli_infp, &c, 1L);
if ( c == 'A') /* shift left */
while ( col )
{
Write( mycli_outfp, "\x08", 1L);
col--;
}
else /* shift right */
while ( col < 70 && s[ col ] != '\0' )
{
Write(mycli_outfp, "\x9bC", 2L);
col++;
}
break;
case 'A': case 'B':
if ( c == 'A' )
currcmd = --currcmd & 15;
else
currcmd = ++currcmd & 15;
for ( i = 0; i < 72; i++)
s[ i ] = '\0';
strcpy( s, &cmdbuf[ currcmd ][ 0 ]);
col = strlen( s );
Write( mycli_outfp, "\r\x9bK", 3L);
showprompt();
strcpy( work, s);
WriteWork();
break;
case 'C': /* cursor right */
if ( col < 70 && s[ col ] != '\0' )
{
Write(mycli_outfp, "\x9bC", 2L);
col++;
}
break;
case 'D': /* cursor left */
if ( col )
{
Write(mycli_outfp, "\x08", 1L);
col--;
}
break;
case '?':
strcpy( s, "help");
return;
}
continue;
default:
if ( c >= ' ' && c <= '~' )
if (insert)
{
if ( strlen(s) < 70)
{
strcpy( work2, &s[ col ]);
s[ col++ ] = c;
s[ col ] = '\0';
strcat( s, work2);
Write( mycli_outfp, "\x9b@", 2L);
}
}
else if ( col < 70)
s[ col++ ] = c;
Write( mycli_outfp, &c, 1L);
continue;
}
break;
}
}
/* --------------------------------------------------------------
* Start of MyCLI internal functions
* --------------------------------------------------------------
*/
#ifdef MODEM
VOID capture(s)
UBYTE *s;
{
if (!modem_online) {
strcpy( work, "\x1b[33mCapture Error: not online\x1b[0m\n");
WriteWork();
}
else if (capturing_file) {
Close(capture_fp);
strcpy( work, "\x1b[33mCapture Completed\x1b[0m\n");
WriteWork();
capturing_file = 0;
}
else {
capture_fp = Open(s, MODE_NEWFILE);
if (capture_fp == 0)
doserr();
else {
capturing_file = !0;
strcpy( work,"\x1b[33mCapturing File - capture again to terminate\x1b[0m\n");
WriteWork();
}
}
}
#endif
VOID cd(s)
UBYTE *s;
{
register WORD i;
register struct FileLock *worklock;
register struct FileInfoBlock *fib;
if ( *s == '\0' )
{
sprintf(work, "%s\n", current_directory);
WriteWork();
return;
}
strcpy( work2, current_directory);
fib = (struct FileInfoBlock *)AllocMem( (long)sizeof(struct FileInfoBlock), MEMF_PUBLIC);
while ( *s == '/') /* go up directory path one dir */
{
s++;
for ( i = strlen(current_directory);
current_directory[ i ] != '/' && current_directory[ i ] != ':' && i ;
i--);
if ( current_directory[ i ] == ':')
current_directory[ i+1 ] = '\0';
else
current_directory[ i ] = '\0';
}
if ( stpchr(s, ':') == 0 ) /* no ':' in the path */
{
if ( *s != '\0' )
makename( current_directory, s); /* add string to current dir */
}
else
strcpy(current_directory, s); /* string is new current dir */
worklock = Lock(current_directory, ACCESS_READ);
if (worklock == 0)
{
strcpy(current_directory, work2);
doserr();
}
else if ( Examine(worklock, fib) )
{
if (fib->fib_DirEntryType > 0L)
worklock = CurrentDir(worklock);
else
{
strcpy( work, "\x1b[33mCD Error: not a directory!\x1b[0m\n");
WriteWork();
strcpy(current_directory, work2);
}
}
else
doserr();
if ( worklock )
UnLock( worklock );
if ( fib )
FreeMem( fib, (long)sizeof(struct FileInfoBlock) );
}
VOID copy(s)
UBYTE *s;
{
register LONG iosize;
register LONG actual;
register UBYTE *copybuf;
register UBYTE *pc;
struct FileLock *worklock;
struct FileInfoBlock *fib;
struct FileHandle *copyin;
struct FileHandle *copyout;
copyin = copyout = NULL;
if ( strncmp( s, "from", 4 ) == 0 ) /* remove keyword 'from' */
s = stpblk( s + 4 );
for ( pc = s; *pc && !isspace( *pc ); pc++ )
;
*pc++ = '\0';
pc = stpblk( pc );
if ( strncmp( pc, "to", 2 ) == 0 ) /* remove keyword 'to' */
pc = stpblk( pc + 2 );
/* check 'from' filename for console. */
if (strncmp(s, "*", 1) == 0)
copyin = mycli_infp;
else
copyin = Open(s, MODE_OLDFILE);
if (copyin == NULL)
{
doserr();
return;
}
/* second parameter */
if (strncmp(pc, "*", 1) == 0) /* the console device */
copyout = mycli_outfp;
else if (*pc == '\0') /* no second parameter so put it here */
{
pc = &s[ strlen(s)-1 ]; /* end of string */
while (pc != s && *pc != ':' && *pc != '/')
pc--;
if ( pc != s )
{
pc++; /* move forward over '/' or ':' */
strcpy(work, current_directory); /* save directory in work */
makename( work, pc); /* add filename to dir */
copyout = Open(work, MODE_NEWFILE);
}
}
else /* either a file or a directory name */
{
strcpy( work, pc); /* put file name in work */
worklock = Lock( work, ACCESS_READ);
if ( worklock )
{
fib = (struct FileInfoBlock *)AllocMem( (long)sizeof(struct FileInfoBlock), MEMF_PUBLIC);
if (!Examine( worklock, fib))
doserr();
else
{
if ( fib->fib_DirEntryType > 0L) /* if it is a directory */
{
pc = &s[ strlen(s)-1 ]; /* end of string of file to be copied*/
while (pc != s && *pc != ':' && *pc != '/')
pc--;
if ( *pc == ':' || *pc == '/' )
pc++;
makename( work, pc); /* add file name to dir name */
}
}
UnLock(worklock);
FreeMem( fib, (long)sizeof(struct FileInfoBlock) );
}
copyout = Open( work, MODE_NEWFILE);
}
if (copyout == NULL)
{
doserr();
Close(copyin);
return;
}
/*
* here is how to determine the length of a
* file. This is the most desirable Amount
* to read from the from file, because it
* requires one head seek, and allows the
* entire track buffer to be used for the
* read.
*/
if ( copyin == mycli_infp)
iosize = 1;
else
{
iosize = Seek(copyin, 0L, OFFSET_END);
iosize = Seek(copyin, 0L, OFFSET_BEGINING);
}
/*
* maybe there isn't enough memory to hold
* the entire from file. the following
* algorithm determines whether 1/2 the
* file file, 1/4, 1/8, etc., will fit
* in memory at a time. if 512 bytes can't
* be allocated, then there is not enough
* memory to do the copy at all.
*/
do
{
copybuf = AllocMem(iosize, MEMF_PUBLIC|MEMF_CLEAR);
if (copybuf == 0)
iosize = iosize/2;
}
while( copybuf == 0 && iosize > 512 );
if (copybuf == 0)
{
strcpy( work, "\x1b[33mCopy Error: Not Enough Memory\x1b[0m\n");
WriteWork();
}
else
do
{
actual = Read(copyin, copybuf, iosize);
if (Write(copyout, copybuf, actual) != actual)
{
doserr();
break;
}
if (copyin == mycli_infp)
{
Write( mycli_outfp, copybuf, (long)actual);
if ( *copybuf == 28 ) /* 28 is a ^\ */
{
Write( mycli_outfp, "\n", 1L);
actual = 0;
}
}
}
while (actual == iosize);
if (copyin && copyin != mycli_infp)
Close(copyin);
if (copyout && copyout != mycli_outfp)
Close(copyout);
if ( copybuf )
FreeMem(copybuf, iosize);
}
/*
* get the date and make it into a printable string
*/
static UBYTE *months[12] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static UBYTE dayspermonth2[12] = { /* non leap years */
31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
};
static UBYTE *dayofweek[] = {
"Sunday ", "Monday ", "Tuesday ", "Wednesday ", "Thursday ",
"Friday ", "Saturday "
};
static LONG day, month, year;
dates(s, dss)
UBYTE *s;
struct DateStamp *dss;
{
register LONG temp;
day = (long)dss->ds_Days;
if( day < 0 ) { /* < 0 around the year 2045 */
strcpy( s,"Date out of range");
return;
}
for( year = 78; (temp = 365 + ((( year & 3) == 0) ? 1 : 0)) <= day;)
{
year++;
day -= temp;
}
for( month = 0; day >= dayspermonth2[ month ]; month++)
{
day -= dayspermonth2[ month ];
if( (month == 1) && ((year & 3) == 0) ) {
day--; /* leap year */
if( day < 0 ) { /* ugly, but needed */
day = 28;
break;
}
}
}
year += 1900;
sprintf(s, "%2ld-%3s-%4ld", day+1, months[ month ], year);
}
VOID date(s)
UBYTE *s;
{
struct DateStamp dss;
DateStamp(&dss);
strcpy( work, dayofweek[ ABS(dss.ds_Days % 7) ] );
dates( work+strlen(work), &dss );
#ifdef MOON
strcat( work, ". The moon is ");
strcat( work, moon() );
#endif /* MOON */
strcat(work, ".\n");
WriteWork();
}
VOID define_function_key(s)
UBYTE *s;
{
register UBYTE *ptr;
register WORD i;
ptr = s; /* set up register */
if ( *ptr == '\0')
{
for ( i = 0; i < 20; i++)
if (function_key_definitions[ i ])
{
sprintf(work, "F%-2d = %s\n", i+1, function_key_definitions[ i ]);
WriteWork();
}
return;
}
i = atoi( ptr + 1 );
if ( ( *ptr != 'f' && *ptr != 'F') || (i < 1 || i > 20) )
{
strcpy( work,"\x1b[33mInvalid function key specified\x1b[0m\n");
WriteWork();
return;
}
ptr++;
if ( function_key_definitions[ --i ] )
{
FreeMem( function_key_definitions[ i ], (long)strlen(function_key_definitions[ i ])+1 );
function_key_definitions[ i ] = 0L;
}
while ( isdigit( *ptr ) )
ptr++;
ptr = stpblk( ptr );
if ( *ptr )
{
function_key_definitions[ i ] = AllocMem((long)strlen(ptr)+1, MEMF_PUBLIC|MEMF_CLEAR);
if (function_key_definitions[ i ] == 0)
{
strcpy( work, "\x1b[33mDefine Error: not enough memory\x1b[0m\n");
WriteWork();
}
else
strcpy(function_key_definitions[ i ], ptr);
}
}
VOID delete(s)
UBYTE *s;
{
if ( !DeleteFile(s) )
doserr();
}
/* MyCLI 'list' command is like AmigaDOS 'list' */
VOID list(s)
UBYTE *s;
{
quit = 0;
dirfun(s);
}
/* MyCLI 'dir' is like AmigaDos 'dir' */
VOID dir(s)
UBYTE *s;
{
register UBYTE *ptr;
quit = 0;
indent = 0;
ptr = s;
while ( *ptr )
ptr++; /* go to end of string */
while ( ptr != s && *ptr != '-' && *ptr != 'o' )
ptr--; /* search back for keyword */
if ( strncmp( ptr, "-r", 2) == 0 || strncmp( ptr, "opt a", 5) == 0 )
{
if ( ptr != s )
ptr--;
*ptr = '\0';
lsmode = 2;
}
else
lsmode = 1;
dirfun(s);
lsmode = 0;
}
dirfun(s)
UBYTE *s;
{
struct FileLock *worklock;
struct FileInfoBlock *fib;
LONG bytecount, blockcount, filecount, dircount;
WORD newline;
UBYTE dirstr[74];
dircount = filecount = bytecount = blockcount = 0L;
newline = 0;
if (*s == '\0')
strcpy( s, current_directory);
worklock = Lock( s, ACCESS_READ);
if (worklock == 0)
{
doserr();
return( 0);
}
fib = (struct FileInfoBlock *)AllocMem( (long)sizeof(struct FileInfoBlock), MEMF_PUBLIC);
if ( !Examine(worklock, fib))
doserr();
else
{
if (fib->fib_DirEntryType < 0L) /* if its a file */
{
showfib( fib);
filecount++;
bytecount += fib->fib_Size;
blockcount += fib->fib_NumBlocks;
}
else /* else its a subdirectory */
while(ExNext(worklock, fib))
{
if (fib->fib_DirEntryType > 0L && lsmode == 2)
{
if (newline )
nextline( TRUE);
sprintf( work, "%s (Dir)", fib->fib_FileName);
WriteWork();
strcpy( dirstr, s);
if ( dirstr[ strlen(dirstr)-1 ] != ':')
strcat( dirstr, "/");
strcat( dirstr, fib->fib_FileName );
indent++;
nextline( TRUE);
dirfun( dirstr );
}
else
{
if ( lsmode)
{
if (fib->fib_DirEntryType > 0L) /* if its a directory */
{
if ( newline)
nextline( TRUE);
sprintf( work, "%s (Dir)\n", fib->fib_FileName);
WriteWork();
newline = FALSE;
}
else
{
sprintf( work, "%-30s ", fib->fib_FileName);
WriteWork();
if ( newline)
nextline( TRUE);
newline = !newline;
}
}
else
{
showfib( fib);
bytecount += fib->fib_Size;
blockcount += fib->fib_NumBlocks;
if (fib->fib_DirEntryType <= 0L)
filecount++;
else /* Djj */
{
dircount++;
blockcount++;
bytecount += 512L;
}
}
}
if (!pause())
quit = TRUE;
if (quit)
break;
} /* end of while */
if ( !lsmode)
{
sprintf(work,"\n%3ld Directories -%3ld Files -%7ld Bytes -%6ld Blocks\n",
dircount, filecount, bytecount, blockcount);
WriteWork();
}
else
{
indent--;
if ( newline)
nextline( TRUE);
else
nextline( FALSE);
}
UnLock(worklock);
}
FreeMem( fib, (long)sizeof(struct FileInfoBlock) );
}
showfib( infib)
struct FileInfoBlock *infib;
{
sprintf(work, "%-25s ", infib->fib_FileName);
WriteWork();
if (infib->fib_DirEntryType > 0L)
sprintf(work, " (Dir) ");
else
sprintf(work, "%6ld ", infib->fib_Size);
WriteWork();
sprintf(work, "%c%c%c%c ",
(infib->fib_Protection & FIBF_READ) ? '-' : 'r',
(infib->fib_Protection & FIBF_WRITE) ? '-' : 'w',
(infib->fib_Protection & FIBF_EXECUTE) ? '-' : 'e',
(infib->fib_Protection & FIBF_DELETE) ? '-' : 'd');
WriteWork();
dates( work, &infib->fib_Date);
strcat(work, " ");
WriteWork();
times( work, &infib->fib_Date);
strcat(work, "\n");
WriteWork();
}
nextline( next)
WORD next;
{
register WORD i;
if ( next)
Write( mycli_outfp, "\n", 1L);
else
Write( mycli_outfp, "\r", 1L);
for ( i=0; i < indent; i++)
Write( mycli_outfp, " ", 2L);
}
VOID endcli(s)
UBYTE *s;
{
register WORD i;
#ifdef MODEM
if (modem_online) {
strcpy( work, "\x1b[33mTerminal Mode Error: Modem still online\x1b[0m\n");
WriteWork();
}
else {
#endif
for ( i = 0; i < 20; i++)
if (function_key_definitions[ i ])
FreeMem(function_key_definitions[ i ], (long)strlen(function_key_definitions[ i ])+1);
if ( mycli_id == 1 )
executive( "ASSIGN C: SYS:C" );
Close( mycli_outfp);
exit( 0L );
#ifdef MODEM
}
#endif
}
VOID help(s)
UBYTE *s;
{
register WORD i;
strcpy( work, "\n\x1b[33m MyCli Help\x1b[0m\n");
WriteWork();
for ( i = 0; help_messages[ i ]; i++)
{
sprintf(work, "%s\n", help_messages[ i ]);
WriteWork();
if ( !pause() )
break;
}
strcpy( work, "\x1b[33m End of Help\x1b[0m\n");
WriteWork();
}
VOID md(s)
UBYTE *s;
{
register struct FileLock *worklock;
worklock = CreateDir(s);
if (worklock == 0)
doserr();
else
UnLock(worklock);
}
VOID more(s)
UBYTE *s;
{
if ( mycli_outfp == mycli_infp ) /* no redirection enables more */
moremode = 1;
type(s);
moremode = 0;
}
VOID newcli(s)
UBYTE *s;
{
register WORD ypos;
if ( *s )
sprintf( work, "run SYS:C/mycli %s", s );
else
{
ypos = 136-(mycli_id+1)*16;
if ( ypos < 0)
ypos = 0;
sprintf(work, "run SYS:C/mycli 505 %d 134 64 %d", ypos, mycli_id+1);
}
executive( work ); /* Execute mycli command */
}
#ifdef MODEM
VOID offline(s)
UBYTE *s;
{
modem_online = 0;
}
#endif
VOID rename(s)
UBYTE *s;
{
register UBYTE *pc;
if ( strncmp( s, "from", 4 ) == 0 ) /* remove keyword 'from' */
s = stpblk( s + 4 );
for ( pc = s; *pc && !isspace( *pc ); pc++ )
;
*pc++ = '\0';
pc = stpblk( pc );
if ( strncmp( pc, "as", 2) == 0 || strncmp( pc, "to", 2 ) == 0 )
pc = stpblk( pc + 2 );
if ( !Rename(s, pc) )
doserr();
}
VOID setcomment(s)
UBYTE *s;
{
register UBYTE *pc;
for ( pc = s; *pc && !isspace( *pc ); pc++ )
;
*pc++ = '\0';
pc = stpblk( pc );
if ( !SetComment(s, pc) )
doserr();
}
VOID set(s)
UBYTE *s;
{
register UBYTE *s2;
if ( strncmp( s, "path", 4) == 0 )
{
s2 = path_string;
s += 4;
}
else if ( strncmp( s, "chain", 5) == 0 )
{
s2 = chain_string;
s += 5;
}
else if ( strncmp( s, "prompt", 6) == 0 )
{
s2 = prompt_string;
s += 6;
}
else
{
strcpy( work, "\x1b[33mUndefined system variable\x1b[0m\n" );
WriteWork();
return;
}
s = stpblk( s );
if ( *s == '=' ) /* remove keyword '=' */
s = stpblk( s + 1 );
if ( *s == '\0' )
{
sprintf( work, "%s\n", s2 );
WriteWork();
}
else
strcpy( s2, s);
}
#ifdef MODEM
VOID TerminalMode(s)
UBYTE *s;
{
UBYTE buf[74];
modem_online = !0; /* signal that modem is live !!! */
if (initialize()) { /* set baud rate, etc. */
Write(mycli_outfp, WelcomeMessage, (long)strlen(WelcomeMessage));
while (modem_online) {
bdoneflag = 0; /* terminal mode on flag */
Write(mycli_outfp, OnlineMessage, (long)strlen(OnlineMessage));
while (!bdoneflag) {
check_keyboard();
check_modem();
}
Write(mycli_outfp, OfflineMessage, (long)strlen(OfflineMessage));
showprompt();
getcommand(buf);
CommandInterpreter(buf);
}
cleanup();
}
modem_online = 0;
}
#endif
times(s, dss)
UBYTE *s;
struct DateStamp *dss;
{
register LONG hours,
minutes,
seconds;
seconds = dss->ds_Tick / 50L;
seconds %= 60L;
minutes = dss->ds_Minute;
hours = minutes / 60L;
minutes %= 60L;
if (hours == 0)
hours = 24L;
sprintf(s, "%2ld:%02ld:%02ld", (hours>12)?hours-12:hours, minutes, seconds);
if ( hours <= 12 )
strcat(s, "a");
else
strcat(s, "p");
}
VOID time(s)
UBYTE *s;
{
struct DateStamp dss;
DateStamp(&dss);
times(work, &dss);
strcat(work, "\n");
WriteWork();
}
VOID type(s)
UBYTE *s;
{
register struct FileHandle *workfp;
register WORD i;
register WORD len2;
register WORD len;
register WORD linecount = 1;
UBYTE c;
workfp = Open(s, MODE_OLDFILE);
if (workfp == 0)
{
doserr();
return;
}
do
{
len = Read(workfp, work2, 512L);
#ifdef MODEM
if ( !modem_online)
{
#endif
len2 = 0;
while ( len2 < len)
{
for ( i=len2; work2[ i ] != '\n' && i < len; i++)
;
Write( mycli_outfp, &work2[ len2 ], (long)(i - len2 + 1));
len2 = i + 1;
if ( moremode)
{
if (++linecount >= 22 && work2[ i ] == '\n')
{
linecount = 1;
strcpy( work, "\x1b[33mPress <SPACEBAR> for more\x1b[0m");
WriteWork();
while( (c = scr_csts()) != ' ')
if ( c == BRK || c == ESC)
{
len = 0;
break;
}
else if ( c == '\r')
{
linecount = 21;
break;
}
strcpy( work, "\r \r");
WriteWork();
}
}
else
if (!pause()) /* quit the type() by short circuit */
len = 0;
}
#ifdef MODEM
}
else
for (len2 = 0; len2 < len; len2++)
{
Write(mycli_outfp, &work2[ len2 ], 1L);
rs_out[ 0 ] = work2[ len2 ];
DoIO(ModemWriteRequest);
if (!TermEcho) /* characters will be echoed back */
{
WaitIO(ModemReadRequest); /* get the echoed character */
i = rs_in[ 0 ];
BeginIO(ModemReadRequest);
}
if ( !pause())
len = 0;
}
#endif
}
while (len == 512);
strcpy( work, "\n\x1b[33m*** End of File\x1b[0m\n");
WriteWork();
Close(workfp);
}
VOID whatis(s)
UBYTE *s;
{
register WORD errorcode;
register WORD i;
if ( *s < '0' || *s > '9' )
{
strcpy( work, "\x1b[33mInvalid errorcode specified\x1b[0m\n");
WriteWork();
return;
}
errorcode = atoi(s);
if (errorcode)
{
for (i=0; errorcodes[ i ].code; i++)
if (errorcodes[ i ].code == errorcode)
break;
if (errorcodes[ i ].code == errorcode)
strcpy(work2, errorcodes[ i ].message);
else
strcpy(work2, "undocumented AmigaDos error code");
sprintf( work, "\x1b[33mAmigaDos Error %d: %s\x1b[0m\n", errorcode, work2);
WriteWork();
}
}
#ifdef MODEM
/*
* This function converts an incoming ANSI escape sequence
* and processes it. A buffer is passed where any function
* key expansion is to take place. If the buffer is modified
* for any reason, this function returns TRUE.
*/
process_event( cmd_line)
UBYTE *cmd_line;
{
WORD i;
UBYTE c;
char event_buffer[ 32 ];
i = 0;
while( TRUE ) {
Read( mycli_infp, &c, 1L);
event_buffer[ i ] = c;
if ( c == '~' || c == '|' )
break;
i++;
}
event_buffer[ i+1 ] = '\0';
if ( event_buffer[ i ] == '~') {
if ( event_buffer[ i ] == '?') {
strcpy( cmd_line, "help");
return( !0);
}
else if ( isdigit( event_buffer[ 0 ]) ) {
if ( function_key( atoi( event_buffer), cmd_line))
return( !0);
}
}
return( 0);
}
initialize()
{
ModemReadRequest = (struct IOExtSer *)AllocMem((long)sizeof(*ModemReadRequest),
MEMF_PUBLIC | MEMF_CLEAR);
ModemReadRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
ModemReadRequest->IOSer.io_Message.mn_ReplyPort = CreatePort("Read_RS", 0L);
if (OpenDevice(SERIALNAME, 0L, ModemReadRequest, 0L))
{
strcpy( work, "\x1b[33mCan't open serial read device\x1b[0m\n");
WriteWork();
DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem(ModemReadRequest, (long)sizeof(*ModemReadRequest));
return( 0);
}
ModemReadRequest->IOSer.io_Command = CMD_READ;
ModemReadRequest->IOSer.io_Length = 1;
ModemReadRequest->IOSer.io_Data = (APTR) &rs_in[0];
ModemWriteRequest = (struct IOExtSer *)AllocMem((long)sizeof(*ModemWriteRequest),
MEMF_PUBLIC | MEMF_CLEAR);
ModemWriteRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
ModemWriteRequest->IOSer.io_Message.mn_ReplyPort = CreatePort("Write_RS",0L);
if (OpenDevice(SERIALNAME, 0L, ModemWriteRequest, 0L))
{
strcpy( work, "\x1b[33mCan't open serial write device\x1b[0m\n");
WriteWork();
DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem(ModemReadRequest, (long)sizeof(*ModemReadRequest));
DeletePort(ModemWriteRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem(ModemWriteRequest, (long)sizeof(*ModemWriteRequest));
return(0);
}
ModemWriteRequest->IOSer.io_Command = CMD_WRITE;
ModemWriteRequest->IOSer.io_Length = 1;
ModemWriteRequest->IOSer.io_Data = (APTR) &rs_out[0];
/* ModemReadRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED; */
ModemReadRequest->io_SerFlags = SERF_SHARED;
ModemReadRequest->io_Baud = 1200;
ModemReadRequest->io_ReadLen = 8;
ModemReadRequest->io_WriteLen = 8;
ModemReadRequest->io_CtlChar = 13110000L;
ModemReadRequest->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO(ModemReadRequest);
ModemReadRequest->IOSer.io_Command = CMD_READ;
BeginIO(ModemReadRequest);
return( !0);
}
cleanup()
{
CloseDevice( ModemReadRequest);
DeletePort( ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem( ModemReadRequest, (long)sizeof(*ModemReadRequest));
CloseDevice( ModemWriteRequest);
DeletePort( ModemWriteRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem( ModemWriteRequest, (long)sizeof(*ModemWriteRequest));
Write(mycli_outfp, GoodbyeMessage, (long)strlen(GoodbyeMessage));
}
check_keyboard()
{
UBYTE *pc;
UBYTE buf[74];
if (WaitForChar(mycli_infp, 1L))
{
Read( mycli_infp, &rs_out[ 0 ], 1L);
switch( (UBYTE)rs_out[ 0 ])
{
case 0x03: /* escape to command mode with ^c */
bdoneflag = !0;
break;
case 0x9b: /* ANSI keyboard char stuff */
if ( process_event(&buf[ 0 ])) /* send the translation */
{
pc = &buf[ 0 ];
while (*pc != '\0')
{
rs_out[ 0 ] = *pc++;
if ( TermEcho)
Write( mycli_outfp, &rs_out[ 0 ], 1L);
DoIO(ModemWriteRequest);
check_modem();
}
rs_out[ 0 ] = '\n';
if ( TermEcho)
Write( mycli_outfp, &rs_out[0], 1L);
DoIO(ModemWriteRequest);
rs_out[ 0 ] = '\r';
DoIO(ModemWriteRequest);
}
break;
case 0x05: /* toggle keystroke echo with ^e */
TermEcho = !TermEcho;
sprintf( work, "\x1b[33mEcho %s\x1b[0m\n", TermEcho?"ON":"OFF");
WriteWork();
break;
default:
if (TermEcho)
Write( mycli_outfp, &rs_out[ 0 ], 1L);
DoIO( ModemWriteRequest);
}
}
}
/*
* Check to see if the Read Request IO has completed from the modem.
*/
check_modem()
{
if ( CheckIO(ModemReadRequest))
{
WaitIO( ModemReadRequest);
rs_in[ 0 ] &= 0x7f;
Write( mycli_outfp, &rs_in[0], 1L);
if ( capturing_file)
Write( capture_fp, &rs_in[ 0 ], 1L);
BeginIO( ModemReadRequest);
}
}
#endif
#ifdef AZTEC
UBYTE *stpblk(str)
register UBYTE *str;
{
while( *str && isspace(*str) )
str++;
return ( str );
}
isdigit(c)
register UBYTE c;
{
return( (c >= '0') && (c <= '9' ) ); /* depends on ASCII relationships */
/* a portable way to do it, but more code
switch( c )
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return TRUE;
}
return FALSE;
*/
}
isspace(c)
register UBYTE c;
{
if ( c == '\t' || c == ' ' || c == '\n' )
return TRUE;
return FALSE;
}
#endif AZTEC
#ifdef MOON
/*
* Phase of the Moon Conversion.
*
* The phase of the moon (in readable ascii) is written into the buffer,
* followed by a null. The routine returns a pointer to the buffer.
*
*/
UBYTE moonbuf[22], *phasetxt[] = {
"new",
"a waxing crescent",
"in its first quarter",
"waxing gibbous",
"full",
"waning gibbous",
"in its last quarter",
"a waning crescent"
};
WORD day_year[] = { /* Days in year for each month */
-1, -1, 30, 58, 89, 119, 150, 180, 211, 241, 272, 303, 333
}; /* Note: Jan. 1 will equal zero */
/* Year, 1978 = 1978; Month, Jan = 1; Day, 1 = 1
*
* The algorithm is accurate for the Gregorian calender only.
*
* The magic numbers used in the phase calculation are as follows:
* 29.5 The moon's period in days.
* 177 29.5 scaled by 6
* 22 (29.5 / 8) scaled by 6 (this gets the phase)
* 11 ((29.5 / 8) / 2) scaled by 6
*
* Theoretically, this should yield a number in the range 0 .. 7. However,
* two days per year, things don't work out too well.
*
* Epact is calculated by the algorithm given in Knuth vol. 1 (calculation
* of Easter).
*/
UBYTE *moon()
{
register LONG cent; /* Century number (1979 = 20) */
register LONG epact; /* Age of the moon on Jan. 1 */
register LONG diy; /* Day in the year */
register LONG golden; /* Moon's golden number */
register LONG phase; /* Moon phase */
if (month < 0 || month > 12) month = 0; /* Just in case */
diy = day + day_year[month] + 2; /* Day in the year */
if ( (month > 2) && ((year & 3) == 0) )
diy++; /* Leapyear fixup */
cent = (year / 100) + 1; /* Century number */
golden = (year % 19) + 1; /* Golden number */
epact = ((11 * golden) + 20 /* Golden number */
+ (((8 * cent) + 5) / 25) - 5 /* 400 year cycle */
- (((3 * cent) / 4) - 12)) % 30; /* Leap year correction */
if (epact <= 0)
epact += 30; /* Age range is 1 .. 30 */
if ((epact == 25 && golden > 11) || epact == 24)
epact++;
phase = (((((diy + epact) * 6) + 11) % 177) / 22) & 7;
strcpy(moonbuf,phasetxt[ phase ]);
return(moonbuf);
}
#endif